package com.lz.filter.mvcHandlerInterceptor;

import com.lz.common.annotation.PreventDuplicateSubmit;
import com.lz.common.utils.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class PreventDuplicateSubmitInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("进入防止重复提交表单拦截器");
        // 如果不是控制器方法直接放行
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        // 获取方法或类上的防重复提交注解
        PreventDuplicateSubmit annotation = method.getAnnotation(PreventDuplicateSubmit.class);
        if (annotation == null) {
            annotation = handlerMethod.getBeanType().getAnnotation(PreventDuplicateSubmit.class);
        }

        // 如果没有注解则放行
        if (annotation == null) {
            return true;
        }

        String userId = getUserId(request); // 获取用户ID
        String methodName = method.getName(); // 方法名
        String requestURI = request.getRequestURI(); // 请求路径

        // 构建Redis key
        String lockKey = buildLockKey(annotation.keyPrefix(), userId, methodName, requestURI);

        try {
            // 尝试获取锁，使用原子性操作 SET key value NX EX seconds
            Boolean acquired = redisTemplate.opsForValue().setIfAbsent(
                    lockKey,
                    "1",
                    annotation.timeout(),
                    TimeUnit.SECONDS
            );

            if (acquired == null || !acquired) {
                // 获取锁失败，说明有重复请求
                response.setContentType("application/json;charset=UTF-8");
                response.setStatus(HttpServletResponse.SC_CONFLICT);
                response.getWriter().write("{\"code\":409,\"message\":\"" + annotation.message() + "\"}");
                return false;
            }
            log.info("退出防重复提交表单拦截器");
            return true;
        } catch (Exception e) {
            // Redis操作异常处理
//            log.error("Redis操作异常", e);

            return true;
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 请求完成后不需要手动释放锁，因为设置了自动过期
    }

    private String getUserId(HttpServletRequest request) {
        // 实现获取用户ID的逻辑
        // 可以从Session、Token或SecurityContext中获取
        return SecurityUtil.getId();
    }

    private String buildLockKey(String prefix, String userId, String methodName, String requestURI) {
        // 构建更复杂的key，考虑请求参数等
        return String.format("%s:%s:%s:%s", prefix, userId, methodName, requestURI);
    }
}